//
//  Tile.m
//  TabulaImaginarius2
//
//  Created by TA2 on 4/29/11.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "Tile.h"
#import "NetworkController.h"

@implementation Tile

@synthesize point;
@synthesize imageName;
@synthesize currentLayerIndex;
@synthesize tokenStack;
@synthesize drawingBuffer;

- (id)init {
	layersForPlayers = [[NSMutableDictionary alloc] init];
    self.currentLayerIndex = 0;
	NSMutableArray *localLayers = [NSMutableArray arrayWithCapacity:10];
	self.tokenStack = [[NSMutableArray alloc] init];
	for (int k = 0; k < 10; k++) {
        DrawingLayer *layer = [[[DrawingLayer alloc] init] autorelease];
		[localLayers addObject:layer];
	}
	[layersForPlayers setObject:localLayers forKey:[Players sharedLocalPlayer].ip];
	currentPathLock = [[NSObject alloc] init];
	currentImageLock = [[NSObject alloc] init];
    currentImage = nil;
	return self;
}

- (void)dealloc {
    [imageName release];
    imageName = nil;
	[tokenStack release];
    tokenStack = nil;
    [layersForPlayers release];
    layersForPlayers = nil;
	[currentPath release];
    currentPath = nil;
	[currentPathLock release];
    currentPathLock = nil;
	[currentImageLock release];
    currentImageLock = nil;
    CGLayerRelease(drawingBuffer);
    drawingBuffer = nil;
    [super dealloc];
}

- (void)bufferImage {
	if (imageName) {
		NSString *path = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:imageName];
		CGLayerRef image = (CGLayerRef)[[LoadedImages sharedLoadedImages].imageLayers objectForKey:path];
		if (!image) {
			NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
			path = [[documentsDirectory stringByAppendingPathComponent:imageName] stringByAppendingString:@".jpg"];
            if(![[NSFileManager defaultManager] fileExistsAtPath:path]) {
                path = [[[[NSBundle mainBundle ] bundlePath] stringByAppendingPathComponent:imageName] stringByAppendingString:@".jpg"];
            }
			@synchronized (currentImageLock) {
				UIImage *image = [UIImage imageWithContentsOfFile:path];
				UIGraphicsBeginImageContext(image.size);
				currentImage = CGLayerCreateWithContext(UIGraphicsGetCurrentContext(), image.size, NULL);
				UIGraphicsEndImageContext();
				UIGraphicsPushContext(CGLayerGetContext(currentImage));
				[image drawInRect:(CGRect){(CGPoint){0, 0}, image.size}];
				UIGraphicsPopContext();
			}
		} else {
			@synchronized (currentImageLock) {
				currentImage = image;
			}
		}
	} else {
        currentImage = nil;
    }
}

- (void)modifyBufferedImage:(UIImage *)image withImagePath:(NSString *)path {
	@synchronized (currentImageLock) {
		currentImage = CGLayerCreateWithContext(UIGraphicsGetCurrentContext(), image.size, NULL);
		UIGraphicsPushContext(CGLayerGetContext(currentImage));
		[image drawInRect:(CGRect){(CGPoint){0, 0}, image.size}];
		UIGraphicsPopContext();
		imageIsModified = YES;
	}
}

- (void)saveAndReleaseBufferedImage {
	@synchronized (currentImageLock) {
		if (currentImage && imageIsModified) {
			NSString *tileName = [[[@"_" stringByAppendingString:[[NSNumber numberWithFloat:point.x] stringValue]] 
								   stringByAppendingString:@"_"] stringByAppendingString:[[NSNumber numberWithFloat:point.y] stringValue]];
			NSString *path;
			if(TARGET_IPHONE_SIMULATOR) {
				path = [[[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:tileName] stringByAppendingString:@".jpg"];
			} else {
				NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
				path = [[documentsDirectory stringByAppendingPathComponent:tileName] stringByAppendingString:@".jpg"];
			}
			imageName = tileName;
			UIGraphicsBeginImageContext((CGSize){120, 120});
			CGContextDrawLayerInRect(UIGraphicsGetCurrentContext(), (CGRect){(CGPoint){0, 0}, (CGSize){120, 120}}, currentImage);
			UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
			UIGraphicsEndImageContext();
			[UIImageJPEGRepresentation(image, 1.0) writeToFile:path atomically:NO];
			currentImage = nil;
			imageIsModified = NO;
		}
	}
}

- (CGLayerRef)getImage {
	if (imageName) {
		@synchronized (currentImageLock) {
			if (!currentImage) {
                [self bufferImage];
			} 
		}
	}
	return currentImage;
}

- (NSString *)getBackgroundPath {
	@synchronized (currentImageLock) {
		if (imageName) {
			NSString *path = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:imageName];
			if (![[LoadedImages sharedLoadedImages].images objectForKey:path]) {
				if(TARGET_IPHONE_SIMULATOR) {
					path = [[[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:imageName] stringByAppendingString:@".jpg"];
				} else {
					NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
					path = [[documentsDirectory stringByAppendingPathComponent:imageName] stringByAppendingString:@".jpg"];
				}
			}
			return path;
		}
	}
	return nil;
}

- (void)clearVisiblePaths {
    @synchronized (layersForPlayers) {
        for (Player *player in [Players sharedAllPlayers]) {
            NSMutableArray *layers = [layersForPlayers objectForKey:player.ip];
            if (layers) {
                for (DrawingLayer *layer in layers) {
                    if (layer.visibleToAllPlayers || [layer.visibleToPlayers containsObject:[Players sharedLocalPlayer]]) {
                        [layer.paths removeAllObjects];
                    }
                }
            }
        }
    }
}

- (void)addPathToLayer:(DrawingPath *)path forLayer:(int)index forPlayer:(Player *)player {
	@synchronized (layersForPlayers) {
		NSMutableArray *layers = [layersForPlayers objectForKey:player.ip];
		if (!layers && [[Players sharedAllPlayers] containsObject:player]) {
			layers = [NSMutableArray arrayWithCapacity:10];
			for (int k = 0; k < 10; k++) {
                DrawingLayer *layer = [[[DrawingLayer alloc] init] autorelease];
				[layers addObject: layer];
			}
			[layersForPlayers setObject:layers forKey:player.ip];
		}
		if (index < 10 && index >= 0) {
			[((DrawingLayer *)[layers objectAtIndex:index]).paths addObject:path];
			[((DrawingLayer *)[layers objectAtIndex:index]).newPaths addObject:path];
		}
	}
	
}

- (NSArray *)getLayersForPlayer:(Player *)player {
	@synchronized (layersForPlayers) {
		if ([layersForPlayers objectForKey:player.ip]) {
			return [NSArray arrayWithArray:[layersForPlayers objectForKey:player.ip]];
		}
	}
	return nil;
}

- (void)addPointToCurrentPath:(CGPoint)newPoint forLayer:(int)index withLineWidth:(float)lineWidth withColor:(UIColor *)color withColorTexturePath:(NSString *)colorTexturePath {
	if (index != currentLayerIndex) {
		[self finalizeCurrentPath];
		if (index < 10 && index >= 0) {
			currentLayerIndex = index;
		}
	}
	@synchronized (currentPathLock) {
		if (!currentPath) {
			currentPath = [[DrawingPath alloc] init];
			currentPath.lineWidth = lineWidth;
			currentPath.color = color;
            currentPath.colorTexturePath = colorTexturePath;
		}
        if ([currentPath.newPoints count] == 0 && [currentPath.points count] > 0) {
            [currentPath.newPoints addObject:[currentPath.points lastObject]];
        }
		[currentPath.points addObject:[NSValue valueWithCGPoint:newPoint]];
        [currentPath.newPoints addObject:[NSValue valueWithCGPoint:newPoint]];
	}
}

- (void)deleteCurrentPath {
	@synchronized (currentPathLock) {
		if (currentPath) {
			[currentPath release];
			currentPath = nil;
		}
	}
}

- (DrawingPath *)getCurrentPath {
	@synchronized (currentPathLock) {
		if (currentPath) {
            DrawingPath *copyOfCurrentPath = [DrawingPath arrayWithArray:currentPath];
            //[currentPath.newPoints removeAllObjects];
			return copyOfCurrentPath;
		}
		return nil;
	}
}

- (void)finalizeCurrentPath {
	//kul med paths om man vill.
	@synchronized (currentPathLock) {
		if (currentPath) {
			@synchronized (layersForPlayers) {
				NSMutableArray *layers = [layersForPlayers objectForKey:[Players sharedLocalPlayer].ip];
				[((DrawingLayer *)[layers objectAtIndex:currentLayerIndex]).paths addObject:currentPath];
				[((DrawingLayer *)[layers objectAtIndex:currentLayerIndex]).newPaths addObject:currentPath];
				[(DrawProtocol *)[[NetworkController sharedNetworkController].networkProtocols objectForKey:([NSString stringWithString:@"DP"])] sendLine:currentPath forPlayer:[Players sharedLocalPlayer] atLayer:currentLayerIndex atPoint:point];
			}
            [currentPath release];
			currentPath = nil;
		}
	}
}


- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeCGPoint:point forKey:@"tilePoint"];
    [coder encodeInt:currentLayerIndex forKey:@"tileLayerIndex"];
    [coder encodeObject:layersForPlayers forKey:@"tileLayersForPlayers"];
    [coder encodeObject:imageName forKey:@"tileImageName"];
    [coder encodeObject:tokenStack forKey:@"tileTokenStack"];
}

- (id)initWithCoder:(NSCoder *)coder {
    self = [super init];
    self.point = [coder decodeCGPointForKey:@"tilePoint"];
    self.currentLayerIndex = [coder decodeIntForKey:@"tileLayerIndex"];
    layersForPlayers = [[coder decodeObjectForKey:@"tileLayersForPlayers"] retain];
    for (NSString *key in [layersForPlayers allKeys]) {
        BOOL found = NO;
        for (Player *player in [Players sharedAllPlayers]) {
            if ([player.ip isEqualToString:key]) {
                found = YES;
            }
        }
        if (!found) {
            Player *player = [[[Player alloc] init] autorelease];
            player.ip = key;
            [[Players sharedPlayers] addObject:player];
        }
    }
    if (![[layersForPlayers allKeys] containsObject:[Players sharedLocalPlayer].ip]) {
        NSMutableArray *localLayers = [NSMutableArray arrayWithCapacity:10];
        for (int k = 0; k < 10; k++) {
            DrawingLayer *layer = [[[DrawingLayer alloc] init] autorelease];
            [localLayers addObject:layer];
        }
        [layersForPlayers setObject:localLayers forKey:[Players sharedLocalPlayer].ip];
    }
    self.imageName = [coder decodeObjectForKey:@"tileImageName"];
    currentPath = nil;
    currentPathLock = [[NSObject alloc] init];
    currentImageLock = [[NSObject alloc] init];
    tokenStack = [[coder decodeObjectForKey:@"tileTokenStack"] retain];
    self.currentLayerIndex = 0;
    currentImage = nil;
    return self;
}

@end
